package chapter5;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author caiya
 * @date 2020/3/29 20:04
 */
@Slf4j
public class PriorityBlockingQueueTest {
    static PriorityBlockingQueue<Task> priorityBlockingQueue = new PriorityBlockingQueue<>(11);

    public static void main(String[] args) {
        /**
         * PriorityBlockingQueue：无界带优先级的阻塞队列
         * 1、原理：
         *      队列元素使用数组存储，底层使用平衡二叉树堆实现，默认使用对象的 compareTo 实现优先级，每次出队都是
         *      优先级最高或者最低的元素；取出元素的顺序和放入顺序无关。
         * 2、boolean offer(E e)：非阻塞插入
         *      由于 PriorityBlockingQueue 是无界的，所以该方法一直返回 true
         * 3、E poll()：非阻塞获取队首元素
         *      1）如果队列为空，则返回 null
         * 4、void put(E e)：底层调用 offer，所以一直返回 true
         * 5、E take()：阻塞获取队首元素，即队列为空时线程阻塞
         * 6、int size()：获取队列大小
         */
        for (int i = 0; i < 10; i++) {
            Task task = new Task();
            task.setPriority(ThreadLocalRandom.current().nextInt(10));
            task.setTaskName("taskName" + i);
            priorityBlockingQueue.offer(task);
        }

        while (!priorityBlockingQueue.isEmpty()) {
            Task task = priorityBlockingQueue.poll();
            if (task != null) {
                task.doSomething();
            }
        }

    }

    @Data
    @Slf4j
    static class Task implements Comparable<Task> {
        private int priority = 0;
        private String taskName;

        @Override
        public int compareTo(Task task) {
            // priority升序
            if (this.priority >= task.getPriority()) {
                return 1;
            }
            return -1;
        }

        public void doSomething() {
            log.debug("{}:{}", this.taskName, this.priority);
        }

    }

}


